﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace ArgusPCLib.Xml
{
	public abstract class SerializableSettings : IDisposable
	{
		static Dictionary<Type, SerializableSettings> initializedSettings;

		static SerializableSettings()
		{
			SerializableSettings.initializedSettings = new Dictionary<Type, SerializableSettings>();
		}

		/// <summary>
		/// Get a <see cref="Stream"/> to save or load the settings.
		/// </summary>
		protected abstract Stream OpenStream();

		protected virtual string XmlRootName { get { return "Settings"; } }

		public abstract void Reset();

		/// <summary>
		/// Default: false
		/// </summary>
		protected virtual bool SaveOnDisposing { get { return false; } }

		public static T Load<T>() where T : SerializableSettings, new()
		{
			Type type = typeof(T);

			SerializableSettings settings;
			lock (SerializableSettings.initializedSettings)
			{
				if (SerializableSettings.initializedSettings.TryGetValue(type, out settings) == true)
					return (T)settings;
			}

			T RetVal = new T();
			using (Stream stream = RetVal.OpenStream())
			{
				using (Deserializer deserializer = Deserializer.FromStream(stream))
				{
					object obj = deserializer.Deserialize();
					if (obj is T)
						RetVal = (T)obj;
				}
			}

			lock(SerializableSettings.initializedSettings)
			{
				SerializableSettings.initializedSettings.Add(type, RetVal);
			}

			return RetVal;
		}

		public void Save()
		{
			using (Stream stream = this.OpenStream())
			{
				using (Serializer serializer = Serializer.FromStream(stream, this.XmlRootName))
				{
					serializer.Serialize(this);
				}
			}
		}

		public void Dispose()
		{
			if (this.SaveOnDisposing)
				this.Save();
		}
	}
}
